31/05/2010

Questions pièges Java n°4 : réponse

Code :

class Util{
public static boolean Print(String s){
System.out.print(s);
return true;
}
}
class Parent{
static int i = Classe.init ( );
}
class Classe extends Parent {
static int i = 4;
static int init() {
assert Util.Print ( "A" );
return i;
}
}
public class AClass {
public static void main(String[ ] args){
Classe c = new Classe( );
Util.Print ( "" +Parent.i);
}
}


Réponse
Le programme affiche "A0"

Explication
Lorsque les assertions sont désactivées, l'évaluation des expressions passées en parametres des assert n'a pas lieu
Cependant, lorsque l'on accède à un objet avant de l'avoir initialisé, il se comporte comme si les assertions étaient activées.
Ici :

- Classe( ) lançe l'initialisation de Classe.
- l'initialisation de Classe lançe l'initialisation de Parent
- l'initialisation de Parent appelle Classe.init();
- Classe.init(); est exécutée comme si les assertions étaient activées, et renvoie Classe.i;
- l'initialisation de Parent se termine
- l'initialisation de Classe met Classe.i = 4;


Le programme affiche donc toujours A0


Point théorique associé
ici

28/05/2010

Questions pièges Java n°3 : réponse

Code :

class AClass {
private static void egale(Integer i1,Integer i2){
if (i1 == i2)
System.out.println(i1 + " == " + i2);
}
public static void main(String[] args) {
egale(4,4);
egale(200,200);
}
}


Réponse
Le programme affiche donc uniquement : "4 == 4"

Explication
Lorsque l'on passe une primitive (ici un int) à une fonction qui attend explicitement le Wrapper associé (ici un Integer), la jvm "boxe" la valeur.
Ce sont donc bien des Integer (et non des int) qui sont comparés à la ligne 3, java ne réalise pas de unboxing par défaut.

La comparaison de la ligne 3 devrait donc toujours renvoyer "faux".

Cependant, java mutualise les Integer dont les valeurs sont comprises entre -128 et 127. Les références i1 et i2 pointent donc :
- sur le même Wrapper lors du premier appel,
- mais sur 2 Wrappers différent lors du second appel.

Le programme affiche donc uniquement : "4 == 4"

Point théorique associé
ici

Questions pièges Java n°2 : réponse

Code :

public class AClass {
public static void method(byte b){}
public static void main(String[] args) {
byte b1 = 2;
byte b2 = 256;
char c = 10-20;
method(2);
method(256);
}
}


Réponse
Les lignes 5, 6, 7 et 8 sont illégales.

Explication
- la ligne 4 devrait être illégale car l'expression "2" est un entier et ne devrait pas pouvoir être assigné à un byte sans cast explicite. Cependant nous sommes dans un des seuls cas particuliers où cette règle ne s'applique pas.
- la ligne 5 elle est illégale, car 256 est un entier qui ne peut pas rentrer dans un byte (les bytes peuvent contenir des valeurs comprises entre -128 et 127). Nous ne sommes donc pas dans le cas particulier de la ligne 3, et le cast implicite n'est pas autorisé.
- la ligne 6 est illégale pour les mêmes raisons
- la ligne 8 est illégale pour les mêmes raisons que la ligne 4.
- la ligne 7 est illégale, car nous somme dans le cadre d'un passage de paramètre, et non pas d'une assignation, il ne s'agit donc pas du cas particulier de la ligne
3.


Point théorique associé
ici